﻿#region summary

// Copyright (c)  YISH. All rights reserved.
// Licensed under the MIT License, See License.txt in the project root for license information.

#endregion

using System;
using System.Diagnostics;
using NSQL.Generator;
using NSQL.Sharpen;

namespace NSQL.Expressions
{
    [DebuggerDisplay("Column:{Name}")]
    public class ColumnExpression : IColumnExpression
    {
        public int Id { get; private set; } = -1;
        public Identifier Name { get; private set; }
        public Identifier Table { get; set; }

        public ColumnExpression(string columnName, bool delimited = false)
        {
            if (columnName is null) throw new ArgumentNullException(nameof(columnName));
            if (columnName.StartsWith("[") && columnName.EndsWith("]"))
            {
                columnName = columnName.Substring(1, columnName.Length - 2);
            }

            var index = columnName.IndexOf('.');
            if (index > -1)
            {
                Table = new Identifier(columnName.Substring(0, index), delimited);
                Name = new Identifier(columnName.Substring(index + 1), delimited);
            }
            else
            {
                Name = new Identifier(columnName, delimited);
            }
        }
        
        public ColumnExpression(Identifier columnName)
        {
            Name = columnName;
        }
        

        public ColumnExpression(int id)
        {
            Id = id;
            Name = $"{{{Id}}}";
        }

        private ColumnExpression()
        {
        }

        public T Accept<T>(IExpressionVisitor<T> visitor) => visitor.Visit(this);
        public void Accept(IExpressionVisitor visitor) => visitor.Visit(this);
        public bool IsValid => Id > 0 || !string.IsNullOrWhiteSpace(Name);

        public ColumnExpression SetTable(string tableName)
        {
            Table = tableName;
            return this;
        }

        public override string ToString() => SqlGenerator.Instance.Generate(this);
        object IDeepClone.DeepCopy()
        {
            return new ColumnExpression
            {
                Id= Id,
                Name = Name,
                Tag = Tag,
                Table = Table
            };
        }

        public override int GetHashCode()
        {
            return 0;
        }

        public override bool Equals(object obj)
        {
            return ReferenceEquals(obj, this);
        }
        
        public static implicit operator ColumnExpression(Identifier columnName) => new ColumnExpression(columnName);

        public static implicit operator ColumnExpression(string columnName) => new ColumnExpression(columnName);

        public static implicit operator ColumnExpression(int id) => new ColumnExpression(id);


        public static IPredicateExpression operator ==(ColumnExpression left, IConstantExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.Equal);

        public static IPredicateExpression operator !=(ColumnExpression left, IConstantExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.NotEqual);

        public static IPredicateExpression operator ==(IConstantExpression left, ColumnExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.Equal);

        public static IPredicateExpression operator !=(IConstantExpression left, ColumnExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.NotEqual);


        public static IPredicateExpression operator ==(ColumnExpression left, ColumnExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.Equal);

        public static IPredicateExpression operator !=(ColumnExpression left, ColumnExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.NotEqual);

        public static IPredicateExpression operator ==(ColumnExpression left, IExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.Equal);

        public static IPredicateExpression operator !=(ColumnExpression left, IExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.NotEqual);


        public static IPredicateExpression operator ==(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.Equal);

        public static IPredicateExpression operator !=(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.NotEqual);


        public static IPredicateExpression operator >(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.Greater);

        public static IPredicateExpression operator <(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.Less);


        public static IPredicateExpression operator >=(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.GreaterOrEqual);

        public static IPredicateExpression operator <=(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.LessOrEqual);

        public object Tag { get; set; }
    }
}